#pragma once
#include <iostream>
#include <queue>
#include <myh/MyLog.hpp>
#include <myh/PthreadMutex.hpp>

template <class T>
class BQueue
{
    static const size_t defaultcap = 10;

public:
    BQueue(size_t cap = defaultcap)
        :_maxcap(cap)
        ,_lownum(cap/2)
        ,_mutex(new PthMutex)
        ,_p_cond(new PthCond)
        ,_c_cond(new PthCond)
    {}
    ~BQueue()
    {
        delete _mutex;
        delete _p_cond;
        delete _c_cond;
    }
    void push(const T &task)
    {
        _mutex->lock();
        while(_qtask.size() == _maxcap)
        {
            _p_cond->wait(_mutex->getlock());
        }
        _qtask.push(task);
        _mutex->unlock();
        if(_qtask.size() > _lownum)_c_cond->signal();
    }

    T /* * */ pop(/*void * args*/)
    {
        _mutex->lock();
        while(_qtask.size() == 0)
        {
            _c_cond->wait(_mutex->getlock());
        }
        T task = _qtask.front();
        _qtask.pop();
        _mutex->unlock();
        if(_qtask.size() <= _lownum)_p_cond->signal();
        return task;
    }

private:
    size_t _maxcap;
    size_t _lownum;
    PthMutex *_mutex;
    PthCond *_p_cond;
    PthCond *_c_cond;
    std::queue<T> _qtask;
};